/**************************************************************************//**
 * @item     CosyOS-II Kernel
 * @file     os_handler.c
 * @brief    SysTick_Handler and PendSV_Replacer
 * @author   迟凯峰
 * @version  V1.0.0
 * @date     2023.10.20
 ******************************************************************************/

#include "os_link.h"

#if SYSCFG_DEBUGGING == __ENABLED__
static s_u32_t usedtime[2];
#endif

void SysTick_Handler(void) MCUCFG_SYSTICK_ATTRIBUTE
{
	s_tid_t _SYS_REG_ i;
	/* 系统滴答时间统计开始 */
	#if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__
	static m_tick_t tick_temp;
	if(s_taskmgr_binary){
		tick_temp = mSysTick_Counter;
	}
	#endif
	/* 软件RTC */
	#if SYSCFG_SOFTRTC == __ENABLED__
	if(true){
		static
		#if SYSCFG_SYSTICKCYCLE > 1000000UL / 65536
		s_u16_t
		#else
		s_u32_t
		#endif
		_SYS_MEM_ counter = 0;
		static s_u8_t _SYS_MEM_ rtc[7] = sInitRealTime;
		static s_gvar_ts accessor = {s_rtc, rtc};
		if(counter < 1000000UL / SYSCFG_SYSTICKCYCLE - 1) counter++;
		else{
			counter = 0;
			s_sign_every.second = true;
			if(rtc[5] < 59) rtc[5]++;
			else{
				rtc[5] = 0;
				s_sign_every.minute = true;
				if(rtc[4] < 59) rtc[4]++;
				else{
					rtc[4] = 0;
					s_sign_every.hour = true;
					if(rtc[3] < 23) rtc[3]++;
					else{
						rtc[3] = 0;
						s_sign_every.day = true;
						if(rtc[6] < 7) rtc[6]++;
						else rtc[6] = 1;
						if(rtc[2] < (rtc[1] == 2 ? s_month2day : s_month0day[rtc[1]])) rtc[2]++;
						else{
							rtc[2] = 1;
							s_sign_every.month = true;
							if(rtc[1] < 12) rtc[1]++;
							else{
								rtc[1] = 1;
								s_sign_every.year = true;
								if(rtc[0] < 99) rtc[0]++;
								else rtc[0] = 0;
							}
						}
					}
				}
			}
		}
		sWrite_GVarAccessor(&accessor);
		*(s_u32_t *)(s_rtc + 0) = *(s_u32_t *)(rtc + 0);
		*(s_u16_t *)(s_rtc + 4) = *(s_u16_t *)(rtc + 4);
		*(s_u8_t  *)(s_rtc + 6) = *(s_u8_t  *)(rtc + 6);
		sWrite_GVarAccessor(NULL);
	}
	#endif
	/* 调用滴答钩子 */
	#if SYSCFG_TICKHOOK == __ENABLED__
	tick_hook();
	#endif
	/* 定时中断 */
	#if OS_TIMINTTOTAL
	i = OS_TIMINTTOTAL;
	while(i--){
		if(s_timint_loader[i] && s_timint_loader[i] < ~0){
			s_timint_loader[i]--;
			if(!s_timint_loader[i]){
				if(s_timint_hookortask[i]){
					sResumeTask_TimInt(i);
				}
				else{
					(*s_timint_handle[i]->hook)();
				}
				if(s_timint_autoreload[i]){
					s_timint_loader[i] = s_timint_reload[i];
				}
			}
		}
	}
	#endif
	/* 定时查询 */
	#if OS_TIMQRYTOTAL
	i = OS_TIMQRYTOTAL;
	while(i--){
		if(s_timqry_loader[i] && s_timqry_loader[i] < ~0){
			s_timqry_loader[i]--;
		}
		if(!s_timqry_loader[i]){
			if((*s_timqry_handle[i]->event)()){
				if(s_timqry_hookortask[i]){
					sResumeTask_TimQry(i);
				}
				else{
					(*s_timqry_handle[i]->hook)();
				}
				if(s_timqry_autoreload[i]){
					s_timqry_loader[i] = s_timqry_reload[i];
				}
				else{
					s_timqry_loader[i] = ~0;
				}
			}
		}
	}
	#endif
	/* 延时定时器 */
	i = OS_TASKTOTAL;
	do{
		if(s_delay_loader[i] && s_delay_loader[i] < ~0){
			s_delay_loader[i]--;
		}
	}while(--i);
	/* 时间片滴答计数 */
	s_tick_counter++;
	/* 安全运行时 */
	#if SYSCFG_SAFERUNTIME == __ENABLED__
	if(s_task_current != NULL && s_task_current->pri && s_task_current->saferuntime){
		s_task_current->counter++;
		if(s_task_current->counter > 1UL * s_task_current->saferuntime * OS_TIMESHARING){
			s_task_current->status = OS_STATUS_OVERTIME;
			s_sign_timeout[s_task_current->tid] = true;
			#if SYSCFG_DEBUGGING == __ENABLED__
			s_alarm.timedout_saferuntime = true;
			#endif
		}
	}
	#endif
	/* 任务管理器相关 */
	#if SYSCFG_DEBUGGING == __ENABLED__
	if(s_taskmgr_binary){
		usedtime[0]++; /* CPU使用时间计数 */
		#if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__
		mSysTick_Counting; /* 系统滴答时间统计 */
		#endif
	}
	#endif
	/* 触发任务调度（定时调度）*/
	if(!s_sign_return){
		s_sign_scheduling = true;
		mPendSV_Set;
	}
}

/* 任务节点 */
#define	node_head       task_node[0]    /*   头节点 */
#define	node_midd       task_node[1]    /* 中间节点 */
#define	node_tail       task_node[2]    /*   尾节点 */
#define	node_curr       node_buff[0]    /* 当前节点 */
#define	node_news       node_buff[1]    /*   新节点 */
#define	node_temp       node_buff[2]    /* 缓存节点 */
#define	node_last       node_curr->last /* 上一节点 */
#define	node_next       node_curr->next /* 下一节点 */

/* 初始化任务队列（CosyOS的任务队列为双向循环链表）*/
#define	init_taskqueue \
	node_head = node_midd = node_tail = \
	node_news->last = node_news->next = node_news
#define	init_node_head  node_curr = node_head /* 初始化  头节点 */
#define	init_node_midd  node_curr = node_midd /* 初始化中间节点 */
#define	move_forward    node_curr = node_last /* 当前节点前移 */
#define	move_backward   node_curr = node_next /* 当前节点后移 */

/* 移除节点（从任务队列中移除当前节点）*/
#define	node_remove \
do{ \
	node_last->next = node_next; \
	node_next->last = node_last; \
	if(node_curr == node_head){ \
		node_head = node_next; \
	} \
	task_queue_len--; \
}while(false)

/* 插入方向 */
#define forward   0x01 /* 向前 */
#define voidward  0x00 /*   空 */
#define backward  0xFF /* 向后 */

/* 前插（新节点插入当前节点之前）*/
#define	insert_forward \
do{ \
	node_news->next = node_curr; \
	node_news->last = node_last; \
	node_last->next = node_news; \
	node_last = node_news; \
	if(node_curr == node_head){ \
		node_head = node_news; \
	} \
	switch(insert_direction){ \
	case forward: \
		insert_direction = voidward; \
		node_midd = node_midd->last; \
	break; \
	case voidward: \
		insert_direction = forward; \
	break; \
	case backward: \
		insert_direction = voidward; \
	break; \
	} \
}while(false)

/* 后插（新节点插入当前节点之后）*/
#define	insert_backward \
do{ \
	node_news->last = node_curr; \
	node_news->next = node_next; \
	node_next->last = node_news; \
	node_next = node_news; \
	if(node_curr == node_tail){ \
		node_tail = node_news; \
	} \
	switch(insert_direction){ \
	case forward: \
		insert_direction = voidward; \
	break; \
	case voidward: \
		insert_direction = backward; \
	break; \
	case backward: \
		insert_direction = voidward; \
		node_midd = node_midd->next; \
	break; \
	} \
}while(false)

/* 抢占式调度 or 时间片轮转调度 */
#define preemptive_or_rotate \
do{ \
	if(!rotate_f){ \
		node_news = node_curr; \
		if(s_task_current == NULL || node_news->pri != s_task_current->pri){ \
			goto __TASK_SCHEDULING; \
		} \
		rotate_f = true; \
	} \
}while(false)

#if SYSCFG_MCUCORE == 80251
#pragma functions(static)
#endif
void PendSV_Replacer(void) MCUCFG_PENDSV_ATTRIBUTE
{
/* 中断异步服务的执行 */
mPendSV_Entry;
/* 任务调度 */
if(s_sign_scheduling)
{
	static s_u8_t  _SYS_MEM_ task_queue_len = 0;
	static s_u8_t  _SYS_MEM_ insert_direction = 0;
	static s_tasknode_tsp _SYS_MEM_ task_node[3] = {NULL, NULL, NULL};
	s_tasknode_tsp _SYS_REG_ node_buff[3];
	#if SYSCFG_DEBUGGING == __ENABLED__
	m_tick_t _SYS_REG_ counter;
	#endif
	m_bit_t push_f = false;
	m_bit_t rotate_f = false;
	/* 调度初始化 */
	mScheduler_INIT;
	/* 启动任务 */
	if(s_task_starter != NULL){
		if(task_queue_len < OS_TASKQUEUELEN_MAX){
			/* 静态创建 */
			#if SYSCFG_TASKCREATEMODE == __STATIC__
			node_news = s_task_starter;
			if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){
				#if SYSCFG_DEBUGGING == __ENABLED__
				s_fault.failed_startuptask = true;
				s_fault.overflow_taskstack = true;
				#endif
				s_startup_code = OS_ECODE_OVERFLOW_TASKSTACK;
				goto __STARTUP_END;
			}
			else{
				mTaskStack_INIT;
				if(node_news->oldpri <= (s_u8_t)(SYSCFG_TASKPRIORITY - 1)){
					node_news->pri = node_news->oldpri;
				}
				else{
					node_news->pri = SYSCFG_TASKPRIORITY - 2;
					#if SYSCFG_DEBUGGING == __ENABLED__
					s_alarm.outrange_taskpriority = true;
					#endif
				}
				node_news->blocktype = 0;
				node_news->ptr = NULL;
				#if SYSCFG_DEBUGGING == __ENABLED__
				node_news->usedtime[0] = 0;
				node_news->usedtime[1] = 0;
				node_news->stacklen_max = MCUCFG_BASICSTACKSIZE;
				#endif
				node_news->counter = 0;
				s_delay_loader[node_news->tid] = 0;
			}
			/* 平衡创建 */
			#elif SYSCFG_TASKCREATEMODE == __BALANCE__
			node_news = s_task_starter;
			if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){
				node_news->stacksize = MCUCFG_BASICSTACKSIZE;
				#if SYSCFG_DEBUGGING == __ENABLED__
				node_news->realloc = true;
				#endif
			}
			#if SYSCFG_DEBUGGING == __ENABLED__
			else{
				node_news->realloc = false;
			}
			#endif
			node_news->bsp = NULL;
			node_news->bsp = (s_u8_t *)s_malloc(node_news->stacksize);
			if(node_news->bsp != NULL){
				mTaskStack_INIT;
				if(node_news->oldpri <= (s_u8_t)(SYSCFG_TASKPRIORITY - 1)){
					node_news->pri = node_news->oldpri;
				}
				else{
					node_news->pri = SYSCFG_TASKPRIORITY - 2;
					#if SYSCFG_DEBUGGING == __ENABLED__
					s_alarm.outrange_taskpriority = true;
					#endif
				}
				node_news->blocktype = 0;
				node_news->ptr = NULL;
				#if SYSCFG_DEBUGGING == __ENABLED__
				node_news->usedtime[0] = 0;
				node_news->usedtime[1] = 0;
				node_news->stacklen_max = MCUCFG_BASICSTACKSIZE;
				#endif
				node_news->counter = 0;
				s_delay_loader[node_news->tid] = 0;
			}
			else{
				#if SYSCFG_DEBUGGING == __ENABLED__
				s_fault.failed_startuptask = true;
				s_fault.mallocfailed_taskstack = true;
				#endif
				s_startup_code = OS_ECODE_MALLOCFAIL_TASKSTACK;
				goto __STARTUP_END;
			}
			/* 动态创建 */
			#elif SYSCFG_TASKCREATEMODE == __DYNAMIC__
			node_news = NULL;
			node_news = (s_tasknode_tsp)s_malloc(sizeof(s_tasknode_ts));
			if(node_news != NULL){
				node_news->stacksize = s_task_starter->stacksize;
				if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){
					node_news->stacksize = MCUCFG_BASICSTACKSIZE;
					#if SYSCFG_DEBUGGING == __ENABLED__
					node_news->realloc = true;
					#endif
				}
				#if SYSCFG_DEBUGGING == __ENABLED__
				else{
					node_news->realloc = false;
				}
				#endif
				node_news->bsp = NULL;
				node_news->bsp = (s_u8_t *)s_malloc(node_news->stacksize);
				if(node_news->bsp != NULL){
					mTaskStack_INIT;
					node_news->tid = s_task_starter->tid;
					if(s_task_starter->oldpri <= (s_u8_t)(SYSCFG_TASKPRIORITY - 1)){
						node_news->pri = s_task_starter->oldpri;
					}
					else{
						node_news->pri = SYSCFG_TASKPRIORITY - 2;
						#if SYSCFG_DEBUGGING == __ENABLED__
						s_alarm.outrange_taskpriority = true;
						#endif
					}
					node_news->status = s_task_status0;
					node_news->blocktype = 0;
					node_news->ptr = NULL;
					#if SYSCFG_DEBUGGING == __ENABLED__
					node_news->name = s_task_starter->name;
					node_news->usedtime[0] = 0;
					node_news->usedtime[1] = 0;
					node_news->stacklen_max = MCUCFG_BASICSTACKSIZE;
					#endif
					node_news->saferuntime = s_task_starter->saferuntime;
					node_news->counter = 0;
					node_news->hand = s_task_starter;
					s_task_starter->node = node_news;
					s_delay_loader[node_news->tid] = 0;
				}
				else{
					s_free(node_news);
					#if SYSCFG_DEBUGGING == __ENABLED__
					s_fault.failed_startuptask = true;
					s_fault.mallocfailed_taskstack = true;
					#endif
					s_startup_code = OS_ECODE_MALLOCFAIL_TASKSTACK;
					goto __STARTUP_END;
				}
			}
			else{
				#if SYSCFG_DEBUGGING == __ENABLED__
				s_fault.failed_startuptask = true;
				s_fault.mallocfailed_tasknode = true;
				#endif
				s_startup_code = OS_ECODE_MALLOCFAIL_TASKNODE;
				goto __STARTUP_END;
			}
			#endif
			/* 新任务加入任务队列 */
			if(!task_queue_len){
				init_taskqueue;
			}
			else{
				init_node_midd;
				if(node_curr != node_tail && node_news->pri <= node_curr->pri){
					do{
						move_backward;
					}while(node_curr != node_tail && node_news->pri <= node_curr->pri);
				}
				else if(node_curr != node_head && node_news->pri > node_curr->pri){
					do{
						move_forward;
					}while(node_curr != node_head && node_news->pri > node_curr->pri);
				}
				if(node_news->pri > node_curr->pri){
					insert_forward;
				}
				else if(node_curr == node_tail && node_curr->pri == 0){
					insert_forward;
				}
				else{
					insert_backward;
				}
			}
			task_queue_len++;
			s_startup_code = OS_ECODE_NOERROR;
		}
		else{
			#if SYSCFG_DEBUGGING == __ENABLED__
			s_fault.failed_startuptask = true;
			s_alarm.overflow_taskqueue = true;
			#endif
			s_startup_code = OS_ECODE_OVERFLOW_TASKQUEUE;
		}
		__STARTUP_END:
		s_task_starter = NULL;
		if(s_sign_return) return;
		s_task_current->blocktype = s_startup_code;
	}
	/**
	 * \brief    任务优先级调整
	 * \detail   如果任务优先级发生改变，执行服务时已从任务队列中移除并加入到临时链表。
	 *           在此，从临时链表中依次取出各任务，并根据任务优先级重新加入到任务队列。
	 */
	if(s_taskpri_tail != NULL){
		node_temp = s_taskpri_tail;
		do{
			node_news = node_temp;
			node_temp = node_temp->last;
			init_node_midd;
			if(node_curr != node_tail && node_news->pri <= node_curr->pri){
				do{
					move_backward;
				}while(node_curr != node_tail && node_news->pri <= node_curr->pri);
			}
			else if(node_curr != node_head && node_news->pri > node_curr->pri){
				do{
					move_forward;
				}while(node_curr != node_head && node_news->pri > node_curr->pri);
			}
			if(node_news->pri > node_curr->pri){
				insert_forward;
			}
			else if(node_curr == node_tail && node_curr->pri == 0){
				insert_forward;
			}
			else{
				insert_backward;
			}
		}while(node_temp != NULL);
		s_taskpri_tail = NULL;
	}
	/**
	 * \brief    查找就绪
	 * \detail   更新任务状态并同步查找可以运行的、优先级最高的任务。
	 */
	init_node_head;
	while(true){
		switch(node_curr->status){
		case OS_STATUS_BLOCKED:
			if(!s_delay_loader[node_curr->tid]){
				node_curr->status = OS_STATUS_READY;
				preemptive_or_rotate;
			}
			else if(node_curr->blocktype != OS_BLOCKED_DELAY){
				switch(node_curr->blocktype & 0x0F){
				case 1:
					if(*(s_u8_t  *)node_curr->ptr){
						node_curr->status = OS_STATUS_FLOATING;
						preemptive_or_rotate;
					}
				break;
				case 2:
					if(*(s_u16_t *)node_curr->ptr){
						node_curr->status = OS_STATUS_FLOATING;
						preemptive_or_rotate;
					}
				break;
				case 4:
					if(*(s_u32_t *)node_curr->ptr){
						node_curr->status = OS_STATUS_FLOATING;
						preemptive_or_rotate;
					}
				break;
				case 0x0F:
					if(!*(s_u8_t *)node_curr->ptr){
						node_curr->status = OS_STATUS_FLOATING;
						preemptive_or_rotate;
					}
				break;
				}
			}
		break;
		case OS_STATUS_FLOATING:
			if(!s_delay_loader[node_curr->tid]){
				node_curr->status = OS_STATUS_READY;
				preemptive_or_rotate;
			}
			else{
				switch(node_curr->blocktype & 0x0F){
				case 1:
					if(*(s_u8_t  *)node_curr->ptr){
						preemptive_or_rotate;
					}
					else{
						node_curr->status = OS_STATUS_BLOCKED;
					}
				break;
				case 2:
					if(*(s_u16_t *)node_curr->ptr){
						preemptive_or_rotate;
					}
					else{
						node_curr->status = OS_STATUS_BLOCKED;
					}
				break;
				case 4:
					if(*(s_u32_t *)node_curr->ptr){
						preemptive_or_rotate;
					}
					else{
						node_curr->status = OS_STATUS_BLOCKED;
					}
				break;
				case 0x0F:
					if(!*(s_u8_t *)node_curr->ptr){
						preemptive_or_rotate;
					}
					else{
						node_curr->status = OS_STATUS_BLOCKED;
					}
				break;
				}
			}
		break;
		case OS_STATUS_READY:
			preemptive_or_rotate;
		break;
		case OS_STATUS_DELETED:
			if(node_curr != s_task_current){
				node_remove;
				#if SYSCFG_TASKCREATEMODE != __STATIC__
				s_free(node_curr->bsp);
				#endif
				#if SYSCFG_TASKCREATEMODE == __DYNAMIC__
				((s_taskhand_tsp)node_curr->hand)->node = NULL;
				s_free(node_curr);
				#endif
			}
		break;
		#if SYSCFG_SAFERUNTIME == __ENABLED__
		case OS_STATUS_OVERTIME:
			if(!s_sign_timeout[node_curr->tid]) {
				node_curr->status = OS_STATUS_READY;
				preemptive_or_rotate;
			}
		break;
		#endif
		}
		move_backward;
		/* 当前任务优先级组查询完毕 -> 当前任务预处理 */
		if(rotate_f && node_curr->pri != s_task_current->pri){
			goto __TASKING_PREPROCESS;
		}
	}
	
	/* 准备任务调度（首次任务调度 -> 新任务预处理）*/
	__TASK_SCHEDULING:
	if(s_task_current == NULL){
		goto __NEWTASK_PREPROCESS;
	}
	
	/* 当前任务预处理 */
	__TASKING_PREPROCESS:{
		mTaskStack_LEN;
		#if SYSCFG_DEBUGGING == __ENABLED__
		if(stacklen > s_task_current->stacklen_max){
			s_task_current->stacklen_max = stacklen;
		}
		#endif
		mEvery_Monitor;
	}
	
	/* 开始任务调度 */
	if(true){
		/* 1、新任务与当前任务优先级不同 -> 当前任务后处理 */
		if(node_news->pri != s_task_current->pri){
			goto __TASKING_POSTPROCESS;
		}
		/* 2、当前任务可以运行 && 时间片未到期 -> 返回 */
		if(s_tick_counter < OS_TIMESHARING && s_task_current->status <= OS_STATUS_FLOATING){
			s_task_current->status = OS_STATUS_READY;
			return;
		}
		/* 3、当前任务不可运行 || 时间片已到期 -> 时间片轮转调度 */
		node_curr = s_task_current;
		move_backward;
		while(node_last != node_tail && node_last->pri == node_curr->pri){
			if(node_curr->status > OS_STATUS_FLOATING){
				move_backward;
			}
			else{
				node_news = node_curr;
				goto __TASKING_POSTPROCESS;
			}
		}
		/* 4、新任务仍为当前任务，说明时间片已到期 -> 返回 */
		if(node_news == s_task_current){
			s_task_current->status = OS_STATUS_READY;
			s_tick_counter = 0;
			return;
		}
	}
	
	/* 当前任务后处理 */
	__TASKING_POSTPROCESS:{
		if(s_task_current->status < OS_STATUS_STOPPED){
			mPUSH_Monitor;
		}
		else if(s_task_current->status == OS_STATUS_DELETED){
			node_curr = s_task_current;
			node_remove;
			#if SYSCFG_TASKCREATEMODE != __STATIC__
			s_free(node_curr->bsp);
			#endif
			#if SYSCFG_TASKCREATEMODE == __DYNAMIC__
			((s_taskhand_tsp)node_curr->hand)->node = NULL;
			s_free(node_curr);
			#endif
		}
	}
	
	/* 新任务预处理 */
	__NEWTASK_PREPROCESS:{
		node_news->status = OS_STATUS_READY;
		s_tick_counter = 0;
		#if SYSCFG_DEBUGGING == __ENABLED__
		if(s_taskmgr_binary) counter = mSysTick_Counter;
		#endif
	}
	
	/* 当前任务入栈 */
	if(push_f){
		#if SYSCFG_DEBUGGING == __ENABLED__
		if(s_taskmgr_binary) mUsedTime_END;
		#endif
		mTaskStack_PUSH;
	}
	
	/* 新任务出栈 */
	if(true){
		#if SYSCFG_DEBUGGING == __ENABLED__
		if(s_taskmgr_binary) mUsedTime_INIT;
		#endif
		mTaskStack_POP;
	}
}
}
